#include <am.h>
#include <klib.h>
#include <klib-macros.h>


#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
#define INT_MIN -2147483648

static unsigned long int next = 1;

int rand(void) {
  // RAND_MAX assumed to be 32767
  next = next * 1103515245 + 12345;
  return (unsigned int)(next/65536) % 32768;
}

void srand(unsigned int seed) {
  next = seed;
}

int abs(int x) {
  return (x < 0 ? -x : x);
}

int atoi(const char* nptr) {
  int x = 0;
  while (*nptr == ' ') { nptr ++; }
  while (*nptr >= '0' && *nptr <= '9') {
    x = x * 10 + *nptr - '0';
    nptr ++;
  }
  return x;
}

//返回字符串长度 
int itoa_klib(int num, char* str, int v){
	//不要给str判空，str本应是空的 
	char tmp[100];
	int index = 0;
	int sign = 1;
	if(v == 10){
		if(num<0) {
			if(INT_MIN) tmp[index++] = '8';//第一次计算时，由于数字超限会截断个位，因此提前补全个位 
			num=-num,sign = 0,index++;
		}	

		do{
			tmp[index++] = num%10 + '0';
			num/=10;
		}while(num);
		assert(index<100);
		tmp[index] = '\0';
		
		if(sign) str_rev(tmp,index);
		else tmp[0]='-',str_rev(tmp+1,index-1);
		
		strcpy(str,tmp);
		return index;
	}else if(v == 16){
		do{
			int n = num%16;
			if(n<10) tmp[index++] = n + '0';
			else tmp[index++] = n - 10 + 'a';
			num/=16;
		}while(num);
		
		str_rev(tmp,index);
		strcpy(str,tmp);
		
		return index;
	}else{
		assert(0);
		return 0;
	}
	
}


//使用malloc申请比较小的空间时，返回值应该位于0x40000000以内，而当malloc申请的空间比较大时，会使用mmap的私有匿名映射实现，所以malloc的返回值应该大于0x40000000

#if !(defined(__ISA_NATIVE__) && defined(__NATIVE_USE_KLIB__))
static char* mptr;
char is_init_malloc = 1;
#endif

void *malloc(size_t size) {
  // On native, malloc() will be called during initializaion of C runtime.
  // Therefore do not call panic() here, else it will yield a dead recursion:
  //   panic() -> putchar() -> (glibc) -> malloc() -> panic()
#if !(defined(__ISA_NATIVE__) && defined(__NATIVE_USE_KLIB__))
	if(is_init_malloc){
		mptr = (void*)ROUNDUP(heap.start,8);
		is_init_malloc = 0;
	}
	size = (size_t)ROUNDUP(size,8);
	char* backup = mptr;
	mptr += size;
	assert((uintptr_t)heap.start <= (uintptr_t)mptr && (uintptr_t)mptr < (uintptr_t)heap.end);
	for (uint64_t *p = (uint64_t *)backup; p != (uint64_t *)mptr; p ++) *p = 0;
	return backup;
#endif
  return NULL;
}

void free(void *ptr) {
}

#endif
